home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / MSC2BC.ARJ / MSCGRF.C < prev    next >
C/C++ Source or Header  |  1991-12-05  |  50KB  |  1,654 lines

  1. /*
  2.    GRAPHICS DEMO FOR Microsoft C6.0a graph.h
  3.    Produces results comparable to those from BGIGRF.C
  4.  
  5.    Copyright (c) 1991 Borland International. All rights reserved.
  6.  
  7.    From the command line, use:
  8.  
  9.         cl mscgrf.c
  10.  
  11. */
  12.  
  13. #include <dos.h>
  14. #include <math.h>
  15. #include <limits.h>
  16. #include <conio.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <stdarg.h>
  20. #include <string.h>
  21. #include <time.h>
  22. #include <graph.h>
  23.  
  24. /* Note 1 - Add the random function, and redefine RAND_MAX from stdlib.h */
  25. #undef RAND_MAX
  26. #define RAND_MAX 0x7FFFU
  27. /* generate an integer random number in the range 0-(num-1) */
  28. #define random(num)(int)(((long)rand()*(num))/(long)(RAND_MAX+1))
  29. /* torad converts degrees to radians */
  30. #define torad( d )    (( (double)(d) * PI ) / 180.0 )
  31.  
  32. /* Note 2 - FONT_PATH is the location of the .FON files used by this program.
  33.    Edit it as appropriate for your environment.
  34. */
  35. #define FONT_PATH "g:\\c600\\source\\samples\\*.FON"
  36.  
  37. /* Note 3 - COLORS, HORIZ_DIR, VERT_DIR, FILLS, predefined fill patterns,
  38.    viewporttype, and SOLID_STYLE are defined below.
  39.    The curr_vp structure is used to keep track of the current state of the
  40.    viewport.
  41.  */
  42. enum COLORS
  43. {
  44.     BLACK,          /* dark colors */
  45.     BLUE,
  46.     GREEN,
  47.     CYAN,
  48.     RED,
  49.     MAGENTA,
  50.     BROWN,
  51.     LIGHTGRAY,
  52.     DARKGRAY,           /* light colors */
  53.     LIGHTBLUE,
  54.     LIGHTGREEN,
  55.     LIGHTCYAN,
  56.     LIGHTRED,
  57.     LIGHTMAGENTA,
  58.     YELLOW,
  59.     WHITE
  60. };
  61. #define HORIZ_DIR   0    /* left to right */
  62. #define VERT_DIR    1   /* bottom to top */
  63.  
  64. enum FILLS
  65. { EMPTY_FILL, SOLID_FILL, LINE_FILL, LTSLASH_FILL, SLASH_FILL, BKSLASH_FILL,
  66.   LTBKSLASH_FILL, HATCH_FILL, XHATCH_FILL, INTERLEAVE_FILL, WIDE_DOT_FILL,
  67.   CLOSE_DOT_FILL
  68. };
  69.  
  70.   static char patterns[][8] = {
  71. /* Empty_Fill, fills area in background color */
  72.    { 0, 0, 0, 0, 0, 0, 0, 0 },
  73. /* Solid_Fill, fills area in solid fill color */
  74.       { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
  75. /* Line_Fill, --- fill */
  76.       { 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0 },
  77. /* LtSlash_Fill, /// fill */
  78.       { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
  79. /* Slash_Fill, /// fill with thick lines */
  80.       { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
  81. /* BkSlash_Fill, \\\ fill with thick lines */
  82.       { 0x99, 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33 },
  83. /* LtBkSlash_Fill, \\\ fill */
  84.       { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
  85. /* Hatch_Fill, light hatch fill */
  86.       { 0x88, 0x55, 0x22, 0x55, 0x88, 0x55, 0x22, 0x55 },
  87. /* XHatch_Fill, heavy cross hatch fill */
  88.       { 0x77, 0xAA, 0xDD, 0xAA, 0x77, 0xAA, 0xDD, 0xAA },
  89. /* Interleave_Fill, interleaving line fill */
  90.       { 0x01, 0x01, 0x01, 0xFF, 0x01, 0x01, 0x01, 0xFF },
  91. /* Wide_Dot_Fill, widely spaced dot fill */
  92.       { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 },
  93. /* Close_Dot_Fill, Closely spaced dot fill */
  94.       { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }
  95. //*    { 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF }  */
  96. };
  97.  
  98. struct viewporttype
  99. {
  100.     int left, top, right, bottom;
  101.     int clip;
  102. };
  103.  
  104. #define SOLID_STYLE 0xFFFF
  105.  
  106. struct viewporttype curr_vp;   /* Current viewport */
  107.  
  108. #define ESC    0x1b            /* Define the escape key    */
  109. #define TRUE    1            /* Define some handy constants    */
  110. #define FALSE    0            /* Define some handy constants    */
  111. #define PI    3.14159         /* Define a value for PI    */
  112. #define ON    1            /* Define some handy constants    */
  113. #define OFF    0            /* Define some handy constants    */
  114.  
  115. /* Note 4 - Define the necessary tables to keep track of the attributes
  116.    of each Microsoft .FON file, and the font family names.
  117.  */
  118. #define NFONTS 300   /* 300 fonts should be enough */
  119. #define NFONTNAMES 100    /* 100 font names should be enough */
  120.  
  121. struct _fontinfo Fonts[NFONTS];
  122.  
  123. unsigned char Font_Names[NFONTNAMES][20];
  124.  
  125. /* Note 5 - Microsoft C graphics has no built-in data about shape fill styles,
  126.    line drawing styles, and text justification.
  127. */
  128. char *FillStyles[] = {
  129.   "EmptyFill",  "SolidFill",      "LineFill",      "LtSlashFill",
  130.   "SlashFill",  "BkSlashFill",    "LtBkSlashFill", "HatchFill",
  131.   "XHatchFill", "InterleaveFill", "WideDotFill",   "CloseDotFill"
  132. };
  133.  
  134. char *TextDirect[] = {
  135.   "HorizDir",  "VertDir"
  136. };
  137.  
  138. struct PTS {
  139.   int x, y;
  140. };    /* Structure to hold vertex points    */
  141. /* Note 6 - The Microsoft graph.h structure videoconfig contains information
  142.    about the configuration of the video adapter on which this program is
  143.    being run after _getvideoconfig is called.  The global variables below
  144.    contain information about the state of the Microsoft graphics system.
  145. */
  146. struct videoconfig vc;        /* Video configuration info */
  147. int    GraphDriver;        /* The Graphics device driver        */
  148. int    GraphMode;        /* The Graphics mode value        */
  149. double AspectRatio;        /* Aspect ratio of a pixel on the screen*/
  150. int    MaxX, MaxY;        /* The maximum resolution of the screen */
  151. int    MaxColors;        /* The maximum # of colors available    */
  152. int    ErrorCode;        /* Reports any graphics errors        */
  153. int    nfonts;            /* Number of fonts available        */
  154. int    nfont_names;        /* Number of typefaces available        */
  155. int    dfont_ndx, dfont_ht;    /* Default font index & height(Courier) */
  156. int    roman_ndx, rfont_ht;    /* Roman font index & height */
  157. struct xycoord cp;        /* Current x,y position of graphics    */
  158. int    gwritemode;        /* Current graphics write mode        */
  159.  
  160. /*                                    */
  161. /*    Function prototypes                        */
  162. /*                                    */
  163.  
  164. void Initialize(void);
  165. void ReportStatus(void);
  166. void TextDump(void);
  167. void RandomBars(void);
  168. void TextDemo(void);
  169. void ColorDemo(void);
  170. void ArcDemo(void);
  171. void CircleDemo(void);
  172. void PieDemo(void);
  173. void BarDemo(void);
  174. void PutPixelDemo(void);
  175. void PutImageDemo(void);
  176. void LineToDemo(void);
  177. void CRTModeDemo(void);
  178. void UserLineStyleDemo(void);
  179. void FillStyleDemo(void);
  180. void PaletteDemo(void);
  181. void PolyDemo(void);
  182. void SayGoodbye(void);
  183. void Pause(void);
  184. void MainWindow(char *header);
  185. void StatusLine(char *msg);
  186. void DrawBorder(void);
  187. void changetextstyle(char *font, int direction, int charht, int charwid);
  188. int  gprintf(int *xloc, int *yloc, char *fmt, ... );
  189. /* Note 7 - Microsoft C does not have a built-in delay function, so we have
  190.    to do it ourselves.
  191.  */
  192. void delay( clock_t wait );
  193.  
  194. /*                                    */
  195. /*    Begin main function                        */
  196. /*                                    */
  197.  
  198. int main()
  199. {
  200.  
  201.   Initialize();         /* Set system into Graphics mode    */
  202.   ReportStatus();        /* Report results of the initialization */
  203.  
  204.     ColorDemo();            /* Begin actual demonstration        */
  205.     if( GraphDriver==_EGA || GraphDriver==_VGA )
  206.       PaletteDemo();
  207.     PutPixelDemo();
  208.     PutImageDemo();
  209.     BarDemo();
  210.     RandomBars();
  211.     ArcDemo();
  212.     CircleDemo();
  213.     PieDemo();
  214.     LineToDemo();
  215.     UserLineStyleDemo();
  216.     TextDump();
  217.     TextDemo();
  218.     CRTModeDemo();
  219.     FillStyleDemo();
  220.     PolyDemo();
  221.     SayGoodbye();        /* Give user the closing screen     */
  222.  
  223.   /* Note 8 - Reset the graphics adapter to text mode with _setvideomode
  224.      before exiting from a Microsoft C graphics program.
  225.    */
  226.   _setvideomode( _DEFAULTMODE ); /* Return the system to text mode    */
  227.   return(0);
  228. }
  229.  
  230. /*                                    */
  231. /* Note 9 - INITIALIZE: Initializes the graphics system and reports    */
  232. /*        any errors which occured.                    */
  233. /*                                    */
  234.  
  235. void Initialize(void)
  236. {
  237.   int i, j, font;
  238.   int     roman_found;
  239.   int     namematch;
  240.   unsigned char list[20];
  241.  
  242.   _setvideomode (_MAXRESMODE);
  243.   _getvideoconfig ( &vc );
  244.   /* These variables are initialized for convenience, and to give symmetry
  245.      between the Microsoft C and Borland C++ versions of this program.
  246.   */
  247.   GraphDriver = vc.adapter;
  248.   GraphMode = vc.mode;
  249.   MaxColors = vc.numcolors;    /* Read maximum number of colors*/
  250.  
  251.   MaxX = vc.numxpixels-1;
  252.   MaxY = vc.numypixels-1;            /* Read size of screen        */
  253.  
  254.     /* initial viewport settings */
  255.     curr_vp.left = 0;
  256.     curr_vp.top  = 0;
  257.     curr_vp.right = MaxX;
  258.     curr_vp.bottom = MaxY;
  259.  
  260.   /* Get correction factor
  261.      Note that 4/3 ratio should come out 1:1
  262.    */
  263.   AspectRatio = (double)vc.numxpixels / (double)vc.numypixels  * (3.0/4.0);
  264.   gwritemode = _getwritemode();
  265.   /* Get number of available fonts */
  266.   nfonts = _registerfonts(FONT_PATH);
  267.   nfont_names = 0;
  268.   dfont_ht = INT_MAX;
  269.   roman_found = 0;
  270.   for( font=1 ; font<=nfonts ; ++font )
  271.   {    /* For each available font    */
  272.     sprintf (list, "n%d", font );
  273.     if( _setfont( list ) >= 0 )
  274.     {
  275.        if( _getfontinfo( &(Fonts[font])) )
  276.        {
  277.      _outtext( "Error: Can't get font information" );
  278.      break;
  279.        }
  280.     }
  281.     /* Use smallest Courier as default font.
  282.        If Courier is not registered, choose the
  283.        smallest bitmapped font registered.
  284.     */
  285.     if (Fonts[font].type == 0) /* bitmapped font */
  286.     {
  287.       if ((strcmp(Fonts[font].facename, "Courier"))==0)
  288.     {
  289.       if(dfont_ht > Fonts[font].pixheight )
  290.       {
  291.         dfont_ht = Fonts[font].pixheight;
  292.         dfont_ndx = font;
  293.       }
  294.     }
  295.     }
  296.     else  /* Vector fonts */
  297.       if (roman_found == 0)    /* Roman found yet? */
  298.     {
  299.     roman_ndx = font;
  300.     rfont_ht = Fonts[font].pixheight;
  301.     if ((strcmp(Fonts[font].facename, "Roman"))==0)
  302.       roman_found = 1;
  303.     }
  304.  
  305.     /* Tabulate the names of all the type faces */
  306.     namematch = 0;
  307.     if (nfont_names > 0)
  308.       for( j=1 ; j<=nfont_names ; ++j )
  309.       {
  310.     if ((strcmp(Fonts[font].facename, &(Font_Names[nfont_names][0])))==0)
  311.     {
  312.       namematch = 1;
  313.       break;
  314.     }
  315.       }
  316.     if (namematch == 0)
  317.       {
  318.       ++nfont_names;
  319.       strcpy (&(Font_Names[nfont_names][0]),Fonts[font].facename);
  320.       }
  321.   }
  322. }
  323.  
  324. /*                                    */
  325. /* Note 10 - REPORTSTATUS: Report the current configuration of the     */
  326. /*         system after the auto-detect initialization.        */
  327. /*                                    */
  328.  
  329. void ReportStatus(void)
  330. {
  331.   struct viewporttype      viewinfo;    /* Params for inquiry procedures*/
  332.  
  333.   char driver[50], mode[50], wmode[50];     /* Strings for driver and mode    */
  334.   unsigned char savemask[8];
  335.  
  336.   int x, y, j;
  337.  
  338.     cp = _getcurrentposition ();
  339.  
  340.   x = 10;
  341.   y = 4;
  342.  
  343.   MainWindow( "Status report after _getvideoconfig" );
  344.  
  345.   switch ( GraphDriver )
  346.     {
  347.     case  _MDPA:
  348.     strcpy(driver,"Monochrome Display Adapter");
  349.     break;
  350.     case  _CGA:
  351.     strcpy(driver,"Color Graphics Adapter");
  352.     break;
  353.     case  _OCGA:
  354.     strcpy(driver,"Olivetti/AT&T Color Graphics Adapter");
  355.     break;
  356.     case  _EGA:
  357.     strcpy(driver,"Enhanced Graphics Adapter");
  358.     break;
  359.     case  _OEGA:
  360.     strcpy(driver,"Olivetti/AT&T Enhanced Graphics Adapter");
  361.     break;
  362.     case  _VGA:
  363.     strcpy(driver,"Video Graphics Array");
  364.     break;
  365.     case  _OVGA:
  366.     strcpy(driver,"Olivetti/AT&T Video Graphics Array");
  367.     break;
  368.     case  _MCGA:
  369.     strcpy(driver,"Multicolor Graphics Array");
  370.     break;
  371.     case  _HGC:
  372.     strcpy(driver,"Hercules Graphics Card");
  373.     break;
  374.     default:     strcpy(driver,"Unknown Graphics Adapter");
  375.     };
  376.  
  377.   switch ( gwritemode )
  378.     {
  379.     case  _GAND:
  380.     strcpy(wmode,"_GAND");
  381.     break;
  382.     case  _GOR:
  383.     strcpy(wmode,"_GOR");
  384.     break;
  385.     case  _GPRESET:
  386.     strcpy(wmode,"_GPRESET");
  387.     break;
  388.     case  _GPSET:
  389.     strcpy(wmode,"_GPSET");
  390.     break;
  391.     case  _GXOR:
  392.     strcpy(wmode,"_GXOR");
  393.     break;
  394.     default:     strcpy(wmode,"Unknown Graphics Write Mode");
  395.     };
  396.  
  397.   gprintf( &x, &y, "Graphics device    : %-20s (%d)", driver, GraphDriver );
  398. /* Can also add MSC text name for mode */
  399.   gprintf( &x, &y, "Graphics mode      : Mode = %d", GraphMode );
  400.   gprintf( &x, &y, "Screen resolution  : ( 0, 0, %d, %d )",
  401.        vc.numxpixels, vc.numypixels );
  402.  
  403.   gprintf( &x, &y, "Current view port  : ( %d, %d, %d, %d )",
  404.        curr_vp.left, curr_vp.top, curr_vp.right, curr_vp.bottom );
  405.  
  406.   gprintf( &x, &y, "Current position   : ( %d, %d )", cp.xcoord, cp.ycoord);
  407.   gprintf( &x, &y, "Colors available   : %d", MaxColors );
  408.   gprintf( &x, &y, "Current color      : %d", _getcolor() );
  409.  
  410.   gprintf( &x, &y, "Line style         : 0x%x", _getlinestyle() );
  411.  
  412.   if (_getfillmask(savemask) == NULL)
  413.     gprintf( &x, &y, "Current fill mask  : NONE" );
  414.   else
  415.     gprintf( &x, &y, "Current fill mask  : 0x%x2%x2%x2%x2%x2%x2%x2%x2",
  416.          savemask[0], savemask[1], savemask[2], savemask[3],
  417.          savemask[4], savemask[5], savemask[6], savemask[7] );
  418.   gprintf( &x, &y, "Graphics write mode: Mode = %s (0x%x)",
  419.        wmode, gwritemode );
  420.   gprintf( &x, &y, "Number of fonts    : %d", nfonts );
  421.   for( j=1 ; j<=nfont_names ; ++j )
  422.   {
  423.     gprintf( &x, &y, "%-20s %s", (j==1) ? "The typefaces are  :" : " ",
  424.          Font_Names[j] );
  425.   }
  426.  
  427.   Pause();                /* Pause for user to read screen */
  428.  
  429. }
  430.  
  431. /*                                    */
  432. /* Note 11 - TEXTDUMP: Display all the characters in each of the     */
  433. /*         available fonts.                        */
  434. /*                                    */
  435.  
  436. void TextDump()
  437. {
  438.   char buffer[80];
  439.   int font, ch, wwidth, lwidth;
  440.   struct viewporttype vp;
  441.  
  442.   for( font=1 ; font<=nfonts ; ++font )
  443.   {    /* For each available font    */
  444.     sprintf( buffer, "%s %s Font, %d Points",
  445.               (Fonts[font].type==0) ? "Bitmapped" : "Scalable",
  446.               Fonts[font].facename, Fonts[font].pixheight );
  447.     MainWindow( buffer );        /* Display fontname as banner    */
  448.     vp.left   = curr_vp.left;
  449.     vp.top    = curr_vp.top;
  450.     vp.right  = curr_vp.right;
  451.     vp.bottom = curr_vp.bottom;
  452.  
  453.     cp = _moveto( 2, 3 );     /* Starting position of first line of text */
  454.  
  455.     buffer[1] = '\0';         /* Terminate a string of one character */
  456.  
  457.     changetextstyle( Fonts[font].facename, HORIZ_DIR,
  458.              Fonts[font].pixheight, Fonts[font].avgwidth );
  459.     ch = '!';            /* Begin at 1st printable    */
  460.     while( ch < 256 )
  461.     {                    /* For each possible character    */
  462.       buffer[0] = ch;            /* Put character into a string    */
  463.       lwidth = _getgtextextent ( buffer ); /* Width of this character */
  464.       if( (cp.xcoord + lwidth+3) >= vp.right)
  465.     /* This line is filled so start a new line of text */
  466.     cp = _moveto( 2, cp.ycoord + Fonts[font].pixheight + 3 );
  467.       _outgtext( buffer );        /* send string to screen    */
  468.       cp = _getcurrentposition ();
  469.       ++ch;                /* Goto the next character    */
  470.     }
  471.  
  472.     Pause();                /* Pause until user acks    */
  473.  
  474.   }                    /* End of FONT loop        */
  475.  
  476. }
  477.  
  478. /*                                    */
  479. /* Note 12 - RANDOMBARS: Display random bars                 */
  480. /*                                    */
  481.  
  482. void RandomBars(void)
  483. {
  484.   int color;
  485.   int x1, y1, x2, y2;
  486.   int prevwritemode;
  487.  
  488.   MainWindow( "Random Rectangles" );
  489.   StatusLine( "Esc aborts or press a key..." ); /* Put msg at bottom of screen   */
  490.   prevwritemode = _setwritemode ( _GPSET );
  491.   while( !kbhit() )
  492.   {            /* Until user enters a key...    */
  493.     x1 = random( MaxX );
  494.     y1 = random( MaxY );
  495.     x2 = random( MaxX );
  496.     y2 = random( MaxY );
  497.     /* The images drawn are normally transparent, i.e. what was written
  498.        previously shows through the fill pattern.
  499.        So we blacken out the area first to achieve the desired effect.
  500.     */
  501.     _setcolor( BLACK );                /* First clear out area */
  502.     _setfillmask( patterns[SOLID_FILL] );
  503.     _rectangle (_GFILLINTERIOR, x1, y1, x2, y2 );
  504.     color = random( MaxColors-1 )+1;
  505.     _setcolor( color );
  506.     _setfillmask( patterns[random(11)] );
  507.     _rectangle (_GBORDER, x1, y1, x2, y2 );
  508.     _rectangle (_GFILLINTERIOR, x1, y1, x2, y2 );
  509.   }
  510.   _setwritemode (prevwritemode);
  511.  
  512.   Pause();                /* Pause for user's response    */
  513.  
  514. }
  515.  
  516.  
  517. /*                                    */
  518. /* Note 13 - TEXTDEMO: Show each font to the user in several sizes.    */
  519. /*                                    */
  520.  
  521. void TextDemo(void)
  522. {
  523.   float charsize[] = { .375, 0.5, .75, 1.0 };
  524.   int font;
  525.   float size, dsize;
  526.   int h, x, y, i, j, lwidth, vh_done;
  527.   struct viewporttype vp;
  528.   char buffer[80];
  529.  
  530.  for( j=1 ; j<=nfont_names ; ++j )
  531.   /* Enumerate all font names */
  532.   {
  533.   sprintf( buffer, "%s Font Demonstration", Font_Names[j] );
  534.   MainWindow( buffer );
  535.   vp.left   = curr_vp.left;
  536.   vp.top    = curr_vp.top;
  537.   vp.right  = curr_vp.right;
  538.   vp.bottom = curr_vp.bottom;
  539.   vh_done = 0;    /* Haven't displayed vertical/horizontal text yet
  540.            for this font family */
  541.   /* Enumerate all the fonts in the table */
  542.   for( font=1 ; font<=nfonts ; ++font )
  543.   if ((strcmp(Fonts[font].facename, &(Font_Names[j][0])))==0)
  544.   /* Font name matches current font name, so display it */
  545.   if (Fonts[font].type == 1)
  546.   {  /* Vector font */
  547.  
  548.     dsize = 0.5;
  549.     /* Display at 1/2 of pixel height */
  550.     changetextstyle( Fonts[font].facename, VERT_DIR,
  551.              (int)(Fonts[font].pixheight*dsize),
  552.              (int)(Fonts[font].avgwidth*dsize) );
  553.     cp = _moveto ((int)(2*Fonts[font].avgwidth*dsize),
  554.      vp.bottom - (int)(2*Fonts[font].pixheight*dsize) );
  555.     _outgtext ( "Vertical" );
  556.     cp = _getcurrentposition ();
  557.     changetextstyle( Fonts[font].facename, HORIZ_DIR,
  558.              (int)(Fonts[font].pixheight*dsize),
  559.              (int)(Fonts[font].avgwidth*dsize) );
  560.     cp = _moveto ( (int)(2*Fonts[font].avgwidth*dsize), 2 );
  561.     _outgtext ( "Horizontal" );
  562.     cp = _getcurrentposition ();
  563.  
  564.     x = (vp.right - vp.left) / 2;
  565.     y = Fonts[font].pixheight;
  566.  
  567.     for( i=1 ; i<=5 ; ++i )
  568.     {        /* For each of the sizes */
  569.       if (i!=5)
  570.     {
  571.     size = charsize[i-1];
  572.     h = (int)(Fonts[font].pixheight*size);
  573.     changetextstyle( Fonts[font].facename, HORIZ_DIR,
  574.              h, (int)(Fonts[font].avgwidth*size) );
  575.     sprintf( buffer, "%d Points", h );
  576.     }
  577.       else
  578.     {
  579.     size = 3.0/2.0;
  580.     h = (int)(Fonts[font].pixheight*size);
  581.     changetextstyle( Fonts[font].facename, HORIZ_DIR,
  582.              h, (int)(Fonts[font].avgwidth*5.0/6.0) );
  583.     sprintf( buffer, "%d Points, 3/2xH, 5/6xW", h );
  584.     }
  585.       y += h;
  586.       lwidth = _getgtextextent (buffer);
  587.       cp = _moveto ( x-(lwidth/2), y );    /* Centered */
  588.       _outgtext ( buffer );
  589.       cp = _getcurrentposition ();
  590.     }    /* for i */
  591.     }    /* Fonts[font].type == 1 */
  592.     else
  593.     {    /* Bitmapped font */
  594.     if (vh_done == 0)
  595.     {
  596.       vh_done = 1;
  597.       changetextstyle( Fonts[font].facename, VERT_DIR,
  598.              Fonts[font].pixheight, Fonts[font].avgwidth );
  599.       cp = _moveto (2*Fonts[font].avgwidth,
  600.             vp.bottom - 2*Fonts[font].pixheight );
  601.       _outgtext ( "Vertical" );
  602.       cp = _getcurrentposition ();
  603.       changetextstyle( Fonts[font].facename, HORIZ_DIR,
  604.              Fonts[font].pixheight, Fonts[font].avgwidth );
  605.       cp = _moveto ( 2*Fonts[font].avgwidth, 2 );
  606.       _outgtext ( "Horizontal" );
  607.       cp = _getcurrentposition ();
  608.  
  609.       x = (vp.right - vp.left) / 2;
  610.       y = Fonts[font].pixheight;
  611.     }
  612.     h = Fonts[font].pixheight;
  613.     changetextstyle( Fonts[font].facename, HORIZ_DIR, h,
  614.              Fonts[font].avgwidth );
  615.     sprintf( buffer, "%d Points", h );
  616.     y += h;
  617.     lwidth = _getgtextextent (buffer);
  618.     cp = _moveto ( x-(lwidth/2), y );    /* Centered */
  619.     _outgtext ( buffer );
  620.     cp = _getcurrentposition ();
  621.     } /* Bitmapped font family */
  622.  
  623.     Pause();                /* Pause to let user look    */
  624.  }  /* for j */
  625.  
  626. }
  627.  
  628. /*                                    */
  629. /* Note 14 - COLORDEMO: Display the current color palette on the screen.*/
  630. /*                                    */
  631.  
  632. void ColorDemo(void)
  633. {
  634.   struct viewporttype vp;
  635.   int color, height, width;
  636.   int twidth;
  637.   int x, y, i, j;
  638.   char cnum[5];
  639.  
  640.   MainWindow( "Color Demonstration" );  /* Show demonstration name      */
  641.  
  642.   color = 1;
  643.   vp.left   = curr_vp.left;
  644.   vp.top    = curr_vp.top;
  645.   vp.right  = curr_vp.right;
  646.   vp.bottom = curr_vp.bottom;
  647.   width  = 2 * ( (vp.right+1) / 16 );       /* Get box dimensions       */
  648.   height = 2 * ( (vp.bottom-10) / 10 );
  649.  
  650.   x = width / 2;
  651.   y = height / 2;    /* Leave 1/2 box border     */
  652.  
  653.   for( j=0 ; j<3 ; ++j )
  654.   {        /* Row loop            */
  655.  
  656.     for( i=0 ; i<5 ; ++i )
  657.     {        /* Column loop            */
  658.  
  659.       _setfillmask(patterns[SOLID_FILL]); /* Set to solid fill in color    */
  660.       _setcolor( color );        /* Set the same border color    */
  661.       /* fill the rectangle    */
  662.       _rectangle( _GFILLINTERIOR, x, y, x+width, y+height );
  663.  
  664.       if( color == BLACK )
  665.       {        /* If box was black...        */
  666.     _setcolor( WHITE );        /* Set drawing color to white    */
  667.     _rectangle( _GBORDER, x, y, x+width, y+height );    /* Outline black in white*/
  668.       }
  669.  
  670.       itoa( color, cnum, 10 );        /* Convert # to ASCII        */
  671.       twidth = _getgtextextent ( cnum );
  672.       cp = _moveto( x +((width-twidth)/2), y+height+4 );    /* Show color # */
  673.       _outgtext ( cnum );
  674.       cp = _getcurrentposition ();
  675.  
  676.       color = ++color % MaxColors;    /* Advance to the next color    */
  677.       x += (width / 2) * 3;        /* move the column base     */
  678.     }                /* End of Column loop        */
  679.  
  680.     y += (height / 2) * 3;        /* move the row base        */
  681.     x = width / 2;            /* reset column base        */
  682.   }                    /* End of Row loop        */
  683.  
  684.   Pause();                /* Pause for user's response    */
  685.  
  686. }
  687.  
  688. /*                                    */
  689. /* Note 15 - ARCDEMO: Display a random pattern of arcs on the screen     */
  690. /*         until the user says enough.                */
  691. /*                                    */
  692.  
  693. void ArcDemo(void)
  694. {
  695.   int mradius;                /* Maximum radius allowed    */
  696.   int eangle;                /* Random end angle of Arc    */
  697.   int mranx, mrany, sangle;
  698.   int starty, endy, startx, endx;
  699.   double radians;
  700.   struct xycoord start, finish, fillseed;
  701.  
  702.   MainWindow( "Arc Demonstration" );
  703.   StatusLine( "ESC Aborts - Press a Key to stop" );
  704.  
  705.   mradius = MaxY / 10;            /* Determine the maximum radius */
  706.  
  707.   while( !kbhit() )
  708.   {            /* Repeat until a key is hit    */
  709.     _setcolor( random( MaxColors - 1 ) + 1 );    /* Randomly select a color    */
  710.     eangle = random( 358 ) + 1;     /* Select an end angle        */
  711.     sangle =  random(eangle);
  712.     mranx  = random(MaxX);
  713.     mrany  = random(MaxY);
  714.     radians = torad( sangle );
  715.     startx = mranx + (int)( cos( radians ) * (double)mradius );
  716.     starty = mrany - (int)( sin( radians ) * (double)mradius );
  717.     radians = torad( eangle );
  718.     endx = mranx + (int)( cos( radians ) * (double)mradius );
  719.     endy = mrany - (int)( sin( radians ) * (double)mradius );
  720.     _arc( mranx+mradius, mrany+mradius,    mranx-mradius, mrany-mradius,
  721.       startx, starty, endx, endy );
  722.     _getarcinfo (&start, &finish, &fillseed);  /* Read coord data */
  723.     cp = _moveto (mranx, mrany);
  724.     _lineto( start.xcoord, start.ycoord ); /* line from start to center */
  725.     cp = _moveto (mranx, mrany);
  726.     _lineto( finish.xcoord, finish.ycoord ); /* line from end to center    */
  727.   }                    /* End of WHILE not KBHIT    */
  728.  
  729.   Pause();                /* Wait for user's response     */
  730.  
  731. }
  732.  
  733. /*                                    */
  734. /* Note 16 - CIRCLEDEMO: Display a random pattern of circles on the    */
  735. /*         screen until the user says enough.                */
  736. /*                                    */
  737.  
  738. void CircleDemo(void)
  739. {
  740.   int mradius;                /* Maximum radius allowed    */
  741.   int mranx, mrany, mranrad;
  742.  
  743.   MainWindow( "Circle Demonstration" );
  744.   StatusLine( "ESC Aborts - Press a Key to stop" );
  745.  
  746.   mradius = MaxY / 10;            /* Determine the maximum radius */
  747.  
  748.   while( !kbhit() )
  749.   {            /* Repeat until a key is hit    */
  750.     _setcolor( random( MaxColors - 1 ) + 1 );    /* Randomly select a color    */
  751.     mranx = random(MaxX);
  752.     mrany = random(MaxY);
  753.     mranrad = random(mradius);
  754.     _ellipse ( _GBORDER, mranx-mranrad, mrany-mranrad,
  755.              mranx+mranrad, mrany+mranrad );
  756.   }                    /* End of WHILE not KBHIT    */
  757.  
  758.   Pause();                /* Wait for user's response     */
  759.  
  760. }
  761.  
  762. /*                                    */
  763. /* Note 17 - PIEDEMO: Display a pie chart on the screen.        */
  764. /*                                    */
  765.  
  766. #define adjasp( y )    ((int)(AspectRatio * (double)(y)))
  767.  
  768. void PieDemo(void)
  769. {
  770.   struct viewporttype vp;
  771.   int xcenter, ycenter, radius, lradius;
  772.   int x, y;
  773.   double radians, piesize;
  774.   int twidth, font;
  775.   float size;
  776.  
  777.   MainWindow( "Pie Chart Demonstration" );
  778.  
  779.   vp.left   = curr_vp.left;
  780.   vp.top    = curr_vp.top;
  781.   vp.right  = curr_vp.right;
  782.   vp.bottom = curr_vp.bottom;
  783.   xcenter = (vp.right - vp.left) / 2;    /* Center the Pie horizontally    */
  784.   ycenter = (vp.bottom - vp.top) / 2+20;/* Center the Pie vertically    */
  785.   radius  = (vp.bottom - vp.top) / 3;    /* It will cover 2/3rds screen    */
  786.   piesize = (vp.bottom - vp.top) / 4.0; /* Optimum height ratio of pie    */
  787.  
  788.   while( (AspectRatio*radius) < piesize ) ++radius;
  789.  
  790.   lradius = radius + ( radius / 5 );    /* Labels placed 20% farther    */
  791.  
  792.   font = roman_ndx;
  793.   changetextstyle( Fonts[font].facename, HORIZ_DIR,
  794.              Fonts[font].pixheight,
  795.              Fonts[font].avgwidth );
  796.   twidth = _getgtextextent ( "A Sample Pie Chart" );
  797.   cp = _moveto( (MaxX-twidth)/2, 6 );
  798.   _outgtext ( "A Sample Pie Chart" );
  799.   cp = _getcurrentposition ();
  800.   size = 0.5;
  801.   changetextstyle( Fonts[font].facename, HORIZ_DIR,
  802.              (int)(Fonts[font].pixheight*size),
  803.              (int)(Fonts[font].avgwidth*size) );
  804.  
  805.   _setfillmask( patterns[SOLID_FILL] );
  806.   _setcolor ( RED );
  807.   _pie ( _GFILLINTERIOR, xcenter+10+radius, ycenter-adjasp(10)+radius,
  808.              xcenter+10-radius, ycenter-adjasp(10)-radius,
  809.              xcenter+10+radius, ycenter-adjasp(10),
  810.              xcenter+10, ycenter-adjasp(10)-radius);
  811.   _setcolor ( WHITE );
  812.   _pie ( _GBORDER, xcenter+10+radius, ycenter-adjasp(10)+radius,
  813.              xcenter+10-radius, ycenter-adjasp(10)-radius,
  814.              xcenter+10+radius, ycenter-adjasp(10),
  815.              xcenter+10, ycenter-adjasp(10)-radius);
  816.   radians = torad( 45 );
  817.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  818.   y = ycenter - (int)( sin( radians ) * (double)lradius /* * AspectRatio */);
  819.   twidth = _getgtextextent ( "25 %" );
  820.   cp = _moveto( x+twidth/2, y );
  821.   _outgtext ( "25 %" );
  822.   cp = _getcurrentposition ();
  823.  
  824.   _setfillmask( patterns[WIDE_DOT_FILL] );
  825.   _setcolor ( GREEN );
  826.   _pie ( _GFILLINTERIOR, xcenter+radius, ycenter+radius,
  827.              xcenter-radius, ycenter-radius,
  828.              xcenter, ycenter-radius,
  829.              xcenter-radius, ycenter-radius);
  830.   _setcolor ( WHITE );
  831.   _pie ( _GBORDER, xcenter+radius, ycenter+radius,
  832.              xcenter-radius, ycenter-radius,
  833.              xcenter, ycenter-radius,
  834.              xcenter-radius, ycenter-radius);
  835.   radians = torad( 113 );
  836.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  837.   y = ycenter - (int)( sin( radians ) * (double)lradius /* * AspectRatio */);
  838.   twidth = _getgtextextent ( "12.5 %" );
  839.   cp = _moveto( x-twidth, y );         /*  twidth/2 ?? */
  840.   _outgtext ( "12.5 %" );
  841.   cp = _getcurrentposition ();
  842.  
  843.   _setfillmask( patterns[INTERLEAVE_FILL] );
  844.   _setcolor ( YELLOW );
  845.   _pie ( _GFILLINTERIOR, xcenter-10+radius, ycenter+radius,
  846.                xcenter-10-radius, ycenter-radius,
  847.                xcenter-10-radius, ycenter-radius,
  848.                xcenter-10-radius, ycenter+radius);
  849.   _setcolor ( WHITE );
  850.   _pie ( _GBORDER, xcenter-10+radius, ycenter+radius,
  851.                xcenter-10-radius, ycenter-radius,
  852.                xcenter-10-radius, ycenter-radius,
  853.                xcenter-10-radius, ycenter+radius);
  854.   radians = torad( 180 );
  855.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  856.   y = ycenter - (int)( sin( radians ) * (double)lradius /* * AspectRatio */);
  857.   twidth = _getgtextextent ( "25 %" );
  858.   cp = _moveto( x-twidth, y+Fonts[roman_ndx].pixheight/2 );
  859.   _outgtext ( "25 %" );
  860.   cp = _getcurrentposition ();
  861.  
  862.   _setfillmask( patterns[HATCH_FILL] );
  863.   _setcolor ( BLUE );
  864.   _pie ( _GFILLINTERIOR, xcenter+radius, ycenter+radius,
  865.              xcenter-radius, ycenter-radius,
  866.              xcenter-radius, ycenter+radius,
  867.              xcenter+radius, ycenter);
  868.   _setcolor ( WHITE );
  869.   _pie ( _GBORDER, xcenter+radius, ycenter+radius,
  870.              xcenter-radius, ycenter-radius,
  871.              xcenter-radius, ycenter+radius,
  872.              xcenter+radius, ycenter);
  873.   radians = torad( 293 );
  874.   x = xcenter + (int)( cos( radians ) * (double)lradius );
  875.   y = ycenter - (int)( sin( radians ) * (double)lradius /* * AspectRatio */);
  876.   twidth = _getgtextextent ( "37.5 %" );
  877.   cp = _moveto( x-twidth/2, y );
  878.   _outgtext ( "37.5 %" );
  879.   cp = _getcurrentposition ();
  880.  
  881.   Pause();                /* Pause for user's response    */
  882.  
  883. }
  884.  
  885. /*                                    */
  886. /* Note 18 - BARDEMO: Draw a 2-D bar chart using _rectangle.         */
  887. /*                                    */
  888.  
  889. void BarDemo(void)
  890. {
  891.   int barheight[] = { 1, 3, 5, 2, 4 };
  892.   int styles[]      = { 1, 3, 10, 5, 9, 1 };
  893.   int xstep, ystep;
  894.   int sheight, swidth;
  895.   int twidth, theight, font;
  896.   int i, j, h;
  897.   struct viewporttype vp;
  898.   char buffer[40];
  899.  
  900.   MainWindow( "2-D Bar Chart Demonstration" );
  901.   vp.left   = curr_vp.left;
  902.   vp.top    = curr_vp.top;
  903.   vp.right  = curr_vp.right;
  904.   vp.bottom = curr_vp.bottom;
  905.   font = roman_ndx;
  906.   changetextstyle( Fonts[font].facename, HORIZ_DIR,
  907.              Fonts[font].pixheight,
  908.              Fonts[font].avgwidth );
  909.   twidth = _getgtextextent ( "These are 2-D Bars" );
  910.   cp = _moveto( (MaxX-twidth) /2, 6 );
  911.   _outgtext( "These are 2-D Bars" );
  912.   cp = _getcurrentposition ();
  913.   font = dfont_ndx;
  914.   changetextstyle( Fonts[font].facename, HORIZ_DIR,
  915.              Fonts[font].pixheight,
  916.              Fonts[font].avgwidth );
  917.   curr_vp.left     = vp.left+50;
  918.   curr_vp.top     = vp.top+30;
  919.   curr_vp.right  = vp.right-50;
  920.   curr_vp.bottom = vp.bottom-10;
  921.   _setviewport( vp.left+50, vp.top+30, vp.right-50, vp.bottom-10 );
  922.  
  923.   vp.left   = curr_vp.left;
  924.   vp.top    = curr_vp.top;
  925.   vp.right  = curr_vp.right;
  926.   vp.bottom = curr_vp.bottom;
  927.  
  928.   sheight = vp.bottom - vp.top;
  929.   swidth  = vp.right  - vp.left;
  930.   h = 3 * Fonts[dfont_ndx].pixheight;
  931.   theight = Fonts[dfont_ndx].pixheight;
  932.   /* Draw vertical axis */
  933.   cp = _moveto (h, h);
  934.   _lineto( h, sheight-h );
  935.   _lineto( sheight-h, sheight-h );
  936.   ystep = (sheight - (2*h) ) / 5;
  937.   xstep = (swidth  - (2*h) ) / 5;
  938.   j = sheight - h;
  939.  
  940.   /* Draw tick marks and numbers for vertical axis */
  941.   for( i=0 ; i<6 ; ++i )
  942.   {
  943.     cp = _moveto (h/2, j);
  944.     _lineto( h, j );
  945.     itoa( i, buffer, 10 );
  946.     twidth = _getgtextextent (buffer);
  947.     cp = _moveto( twidth/2, j-theight/2 );
  948.     _outgtext (    buffer );
  949.     cp = _getcurrentposition ();
  950.     j -= ystep;
  951.   }
  952.  
  953.   j = h;
  954.   for( i=0 ; i<6 ; ++i )
  955.   {
  956.     _setfillmask( patterns[styles[i]] );
  957.     cp = _moveto (j, sheight - h);
  958.     _lineto( j, sheight- 3 - (h/2) );
  959.     itoa( i, buffer, 10 );
  960.     twidth = _getgtextextent ( buffer );
  961.     cp = _moveto( j-(twidth/2), sheight - (h/2));
  962.     _outgtext ( buffer );
  963.     cp = _getcurrentposition ();
  964.     if( i != 5 )
  965.     {
  966.       _setcolor ( 1+random(MaxColors) );
  967.       _rectangle( _GFILLINTERIOR, j, (sheight-h)-(barheight[i] * ystep),
  968.           j+xstep, sheight-h);
  969.       _setcolor ( MaxColors-1 );
  970.       _rectangle( _GBORDER, j, (sheight-h)-(barheight[i] * ystep),
  971.           j+xstep, sheight-h);
  972.     }
  973.     j += xstep;
  974.   }
  975.  
  976.   Pause();
  977.  
  978. }
  979.  
  980. /*                                    */
  981. /*    PUTPIXELDEMO: Display a pattern of random dots on the screen    */
  982. /*    and pick them back up again.                    */
  983. /*                                    */
  984.  
  985. void PutPixelDemo(void)
  986. {
  987.   int seed = 1958;
  988.   int i, x, y, h, w, color;
  989.   struct viewporttype vp;
  990.  
  991.   MainWindow( "_setpixel / _getpixel Demonstration" );
  992.  
  993. //  getviewsettings( &vp );
  994.   vp.left   = curr_vp.left;
  995.   vp.top    = curr_vp.top;
  996.   vp.right  = curr_vp.right;
  997.   vp.bottom = curr_vp.bottom;
  998.   h = vp.bottom - vp.top;
  999.   w = vp.right    - vp.left;
  1000.  
  1001.   srand( seed );            /* Restart random # function    */
  1002.  
  1003.   for( i=0 ; i<5000 ; ++i )
  1004.   {        /* Put 5000 pixels on screen    */
  1005.     x = 1 + random( w - 1 );        /* Generate a random location    */
  1006.     y = 1 + random( h - 1 );
  1007.     color = random( MaxColors );
  1008.     _setcolor( color );
  1009.     _setpixel( x, y );
  1010.   }
  1011.  
  1012.   srand( seed );            /* Restart Random # at same #    */
  1013.  
  1014.   for( i=0 ; i<5000 ; ++i )
  1015.   {        /* Take the 5000 pixels off    */
  1016.     x = 1 + random( w - 1 );        /* Generate a random location    */
  1017.     y = 1 + random( h - 1 );
  1018.     color = _getpixel( x, y );        /* Read the color pixel     */
  1019.     if( color == random( MaxColors ) )    /* Used to keep RANDOM in sync    */
  1020.       {
  1021.       _setcolor ( 0 );
  1022.       _setpixel( x, y );        /* Write pixel to BLACK     */
  1023.       }
  1024.   }
  1025.  
  1026.   Pause();                /* Wait for user's response     */
  1027.  
  1028. }
  1029.  
  1030. /*                                    */
  1031. /*   PUTIMAGEDEMO                            */
  1032. /*                                    */
  1033. void PutImageDemo(void)
  1034. {
  1035.   static int r        = 20;
  1036.   static int StartX = 100;
  1037.   static int StartY = 50;
  1038.   int seed = 2047;
  1039.  
  1040.   struct viewporttype vp;
  1041.   int PauseTime, x, y, ulx, uly, lrx, lry, size, i, width, height, step;
  1042.   void *Saucer;
  1043.  
  1044.   MainWindow("_getimage / _putimage Demonstration");
  1045.   StatusLine( "ESC Aborts - Press a Key to stop" );
  1046.   vp.left   = curr_vp.left;
  1047.   vp.top    = curr_vp.top;
  1048.   vp.right  = curr_vp.right;
  1049.   vp.bottom = curr_vp.bottom;
  1050.  
  1051.   /* Draw Saucer */
  1052.   _setfillmask( patterns[SOLID_FILL] );
  1053.   _setcolor ( MaxColors );
  1054.   _ellipse ( _GFILLINTERIOR, StartX+r, StartY+((r/3)+2),
  1055.                  StartX-r, StartY-((r/3)+2) );
  1056.  
  1057.   cp = _moveto (StartX+7, StartY-6);
  1058.   _lineto(StartX+10, StartY-12);
  1059.   _ellipse (_GBORDER, StartX+8, StartY-14, StartX+12, StartY-10);
  1060.   cp = _moveto (StartX-7, StartY-6);
  1061.   _lineto(StartX-10, StartY-12);
  1062.   _ellipse (_GBORDER, StartX-12, StartY-14, StartX-8, StartY-10);
  1063.  
  1064.   /* Read saucer image */
  1065.   ulx = StartX-(r+1);
  1066.   uly = StartY-14;
  1067.   lrx = StartX+(r+1);
  1068.   lry = StartY+(r/3)+3;
  1069.   width = lrx - ulx + 1;
  1070.   height = lry - uly + 1;
  1071.   size = _imagesize(ulx, uly, lrx, lry);
  1072.  
  1073.   Saucer = malloc( size );
  1074.   _getimage(ulx, uly, lrx, lry, Saucer);
  1075.   _putimage(ulx, uly, Saucer, _GXOR);
  1076.  
  1077. /* Plot some "stars"  */
  1078.   for ( i=0 ; i<1000; ++i )
  1079.     {
  1080.     _setcolor (random( MaxColors-1 )+1);
  1081.     _setpixel(random(MaxX), random(MaxY) );
  1082.     }
  1083.   x = MaxX / 2;
  1084.   y = MaxY / 2;
  1085.   PauseTime = 70;
  1086.  
  1087.    /* Restart random number generator with prime seed to ensure largest
  1088.      cycle of random numbers.
  1089.    */
  1090.   srand(seed);
  1091.   /* until a key is hit */
  1092.   while ( !kbhit() )
  1093.   {
  1094.  
  1095.     /* Draw the Saucer */
  1096.     _putimage(x, y, Saucer, _GXOR);             /*  draw image  */
  1097.     delay(PauseTime);
  1098.     _putimage(x, y, Saucer, _GXOR);             /* erase image  */
  1099.  
  1100.     /* Move Saucer */
  1101.  
  1102.     step = random( 2*r );
  1103.     if ((step/2) % 2 != 0 )
  1104.       step = -1 * step;
  1105.     x = x + step;
  1106.     step = random( r );
  1107.     if ((step/2) % 2 != 0 )
  1108.       step = -1 * step;
  1109.     y = y + step;
  1110.  
  1111.     if (vp.left + x + width - 1 > vp.right)
  1112.       x = vp.right-vp.left-width + 1;
  1113.     else
  1114.       if (x < 0)
  1115.     x = 0;
  1116.     if (vp.top + y + height - 1 > vp.bottom)
  1117.       y = vp.bottom-vp.top-height + 1;
  1118.     else
  1119.       if (y < 0)
  1120.     y = 0;
  1121.   }
  1122.   free( Saucer );
  1123.   Pause();
  1124. }
  1125.  
  1126.  
  1127. /*                                    */
  1128. /*    LINETODEMO: Display a pattern using moveto and lineto commands. */
  1129. /*                                    */
  1130.  
  1131. #define MAXPTS    15
  1132.  
  1133. void LineToDemo(void)
  1134. {
  1135.   struct viewporttype vp;
  1136.   struct PTS points[MAXPTS];
  1137.   int i, j, h, w, xcenter, ycenter;
  1138.   int radius, angle, step;
  1139.   double  rads;
  1140.  
  1141.   MainWindow( "_moveto/_lineto Demonstration" );
  1142.  
  1143.   vp.left   = curr_vp.left;
  1144.   vp.top    = curr_vp.top;
  1145.   vp.right  = curr_vp.right;
  1146.   vp.bottom = curr_vp.bottom;
  1147.   h = vp.bottom - vp.top;
  1148.   w = vp.right    - vp.left;
  1149.  
  1150.   xcenter = w / 2;            /* Determine the center of circle */
  1151.   ycenter = h / 2;
  1152.   radius  = (int)((h - 30) / (AspectRatio * 2));
  1153.   step      = 360 / MAXPTS;        /* Determine # of increments    */
  1154.  
  1155.   angle = 0;                /* Begin at zero degrees    */
  1156.   for( i=0 ; i<MAXPTS ; ++i )
  1157.   {        /* Determine circle intercepts    */
  1158.     rads = (double)angle * PI / 180.0;    /* Convert angle to radians    */
  1159.     points[i].x = xcenter + (int)( cos(rads) * radius );
  1160.     points[i].y = ycenter - (int)( sin(rads) * radius * AspectRatio );
  1161.     angle += step;            /* Move to next increment    */
  1162.   }
  1163.  
  1164.   _ellipse ( _GBORDER, xcenter-radius, ycenter-radius,
  1165.          xcenter+radius, ycenter+radius );
  1166.  
  1167.   for( i=0 ; i<MAXPTS ; ++i )
  1168.   {        /* Draw the chords to the circle */
  1169.     for( j=i ; j<MAXPTS ; ++j )
  1170.     {    /* For each remaining intersect */
  1171.       cp = _moveto(points[i].x, points[i].y); /* Move to beginning of chord    */
  1172.       _lineto(points[j].x, points[j].y); /* Draw the chord        */
  1173.     }
  1174.   }
  1175.  
  1176.   Pause();                /* Wait for user's response     */
  1177.  
  1178. }
  1179.  
  1180. /*                                    */
  1181. /*    CRTMODEDEMO: Demonstrate the effects of the change mode     */
  1182. /*    commands on the current screen.                 */
  1183. /*                                    */
  1184.  
  1185. void CRTModeDemo(void)
  1186. {
  1187.   struct viewporttype vp;
  1188.   int mode, lwidth;
  1189.  
  1190.   MainWindow( "_setvideomode Text & Graphics Demo" );
  1191.   vp.left   = curr_vp.left;
  1192.   vp.top    = curr_vp.top;
  1193.   vp.right  = curr_vp.right;
  1194.   vp.bottom = curr_vp.bottom;
  1195.  
  1196.   lwidth = _getgtextextent ( "Now you are in graphics mode..." );
  1197.   cp = _moveto( (vp.right-vp.left-lwidth)/2, (vp.bottom-vp.top)/2 );
  1198.   _outgtext ( "Now you are in graphics mode..." );
  1199.   cp = _getcurrentposition ();
  1200.   StatusLine( "Press any key for text mode..." );
  1201.   getch();
  1202.  
  1203.   _setvideomode( _DEFAULTMODE );
  1204.   printf( "Now you are in text mode.\n\n" );
  1205.   printf( "Press any key to go back to graphics..." );
  1206.   getch();
  1207.  
  1208.   _setvideomode( _MAXRESMODE );
  1209.   MainWindow( "SetGraphMode / RestoreCRTMode demo" );
  1210.   lwidth = _getgtextextent ( "Back in Graphics Mode..." );
  1211.    cp = _moveto( (vp.right-vp.left-lwidth)/2, (vp.bottom-vp.top)/2 );
  1212.   _outgtext ( "Back in Graphics Mode..." );
  1213.   cp = _getcurrentposition ();
  1214. //  outtextxy( (vp.right-vp.left)/2, (vp.bottom-vp.top)/2,
  1215. //  "Back in Graphics Mode..." );
  1216.  
  1217.   Pause();                /* Wait for user's response     */
  1218.  
  1219. }
  1220.  
  1221. /*                                    */
  1222. /*    USERLINESTYLEDEMO: Display line styles showing the user     */
  1223. /*    defined line style functions.                    */
  1224. /*                                    */
  1225.  
  1226. void UserLineStyleDemo(void)
  1227. {
  1228.   int x, y, i, h, flag;
  1229.   unsigned int style;
  1230.   struct viewporttype vp;
  1231.  
  1232.   MainWindow( "User Defined Line Styles" );
  1233.  
  1234.   vp.left   = curr_vp.left;
  1235.   vp.top    = curr_vp.top;
  1236.   vp.right  = curr_vp.right;
  1237.   vp.bottom = curr_vp.bottom;
  1238.   h = vp.bottom - vp.top;
  1239.  
  1240.   x = 4;
  1241.   y = 10;
  1242.   style = 0;
  1243.   i = 0;
  1244.  
  1245. //  settextjustify( CENTER_TEXT, TOP_TEXT );
  1246.   flag = TRUE;                /* Set the bits in this pass    */
  1247.  
  1248.   while( x < vp.right-2 )
  1249.   {        /* Draw lines across the screen */
  1250.  
  1251.     if( flag )                /* If flag, set bits...     */
  1252.       style = style | (1 << i);     /*    Set the Ith bit in word    */
  1253.     else                /* If no flag, clear bits    */
  1254.     style = style & !(0x8000 >> i);    /*    Clear the Ith bit in word */
  1255.  
  1256.     _setlinestyle( style );
  1257.     cp = _moveto (x, y);
  1258.     _lineto( x, h-y );        /* Draw the new line pattern    */
  1259.  
  1260.     x += 5;                /* Move the X location of line    */
  1261.     i = ++i % 16;            /* Advance to next bit pattern    */
  1262.  
  1263.     if( style == 0xffff )
  1264.     {        /* Are all bits set?        */
  1265.       flag = FALSE;            /*   begin removing bits    */
  1266.       i = 0;                /* Start with whole pattern    */
  1267.     }
  1268.     else
  1269.     {                /* Bits not all set...        */
  1270.       if( style == 0 )            /* Are all bits clear?        */
  1271.     flag = TRUE;            /*   begin setting bits     */
  1272.     }
  1273.   }
  1274.  
  1275.   Pause();                /* Wait for user's response     */
  1276.  
  1277. }
  1278.  
  1279. /*                                    */
  1280. /* Note 19 - FILLSTYLEDEMO: Display with various user-defined fill      */
  1281. /*         patterns.                            */
  1282. /*                                    */
  1283.  
  1284. void FillStyleDemo(void)
  1285. {
  1286.   int h, w, style;
  1287.   int i, j, x, y;
  1288.   struct viewporttype vp;
  1289.   char buffer[40];
  1290.   int lwidth;
  1291.  
  1292.   MainWindow( "User Defined Fill Styles" );
  1293.  
  1294.   vp.left   = curr_vp.left;
  1295.   vp.top    = curr_vp.top;
  1296.   vp.right  = curr_vp.right;
  1297.   vp.bottom = curr_vp.bottom;
  1298.   w = 2 * ((vp.right  +  1) / 13);
  1299.   h = 2 * ((vp.bottom - 10) / 10);
  1300.  
  1301.   x = w / 2;
  1302.   y = h / 2;        /* Leave 1/2 blk margin     */
  1303.   style = 0;
  1304.  
  1305.   for( j=0 ; j<3 ; ++j )
  1306.   {        /* Three rows of boxes        */
  1307.     for( i=0 ; i<4 ; ++i )
  1308.     {        /* Four column of boxes     */
  1309.       _setfillmask( patterns[style] );         /* Iterate thru all styles */
  1310.       _setcolor (MaxColors-1); /* Set the fill style and WHITE */
  1311.       _rectangle( _GBORDER, x, y, x+w, y+h ); /* Draw the border */
  1312.       _rectangle( _GFILLINTERIOR, x, y, x+w, y+h ); /* Draw the actual box */
  1313.       itoa( style, buffer, 10 );    /* Convert style 3 to ASCII    */
  1314.       lwidth = _getgtextextent ( buffer ); /* Width of this label */
  1315.       cp = _moveto( x+((w-lwidth)/2), y+h+4 );
  1316.       _outgtext ( buffer );
  1317.       cp = _getcurrentposition ();
  1318.       ++style;                /* Go on to next style #    */
  1319.       x += (w / 2) * 3;         /* Go to next column        */
  1320.     }                /* End of coulmn loop        */
  1321.     x = w / 2;                /* Put base back to 1st column    */
  1322.     y += (h / 2) * 3;            /* Advance to next row        */
  1323.   }                    /* End of Row loop        */
  1324.  
  1325.   Pause();                /* Wait for user's response     */
  1326.  
  1327. }
  1328.  
  1329. /*                                    */
  1330. /* Note 20 - PALETTEDEMO: Display a pattern of rectangles on the screen    */
  1331. /*         and change palette colors until the user says enough.    */
  1332. /*                                    */
  1333.  
  1334. /* Macro for mixing Red, Green, and Blue elements of color */
  1335. #define RGB(r,g,b) (((long) ((b) << 8 | (g)) << 8) | (r))
  1336. void PaletteDemo(void)
  1337. {
  1338.   int i, j, x, y, color;
  1339.   struct viewporttype vp;
  1340.   int height, width;
  1341.   int relt, gelt, belt;
  1342.  
  1343.   MainWindow( "Palette Demonstration" );
  1344.   StatusLine( "Press any key to continue, ESC to Abort" );
  1345.  
  1346. //  getviewsettings( &vp );
  1347.   vp.left   = curr_vp.left;
  1348.   vp.top    = curr_vp.top;
  1349.   vp.right  = curr_vp.right;
  1350.   vp.bottom = curr_vp.bottom;
  1351.   width  = (vp.right - vp.left) / 15;    /* get width of the box     */
  1352.   height = (vp.bottom - vp.top) / 10;    /* Get the height of the box    */
  1353.  
  1354.   x = y = 0;                /* Start in upper corner    */
  1355.   color = 1;                /* Begin at 1st color        */
  1356.  
  1357.   for( j=0 ; j<10 ; ++j )
  1358.   {        /* For 10 rows of boxes     */
  1359.     for( i=0 ; i<15 ; ++i )
  1360.     {        /* For 15 columns of boxes    */
  1361.       _setfillmask( patterns[SOLID_FILL]);
  1362.       _setcolor ( color++ );    /* Set the color of box */
  1363.         /* Draw the box     */
  1364.       _rectangle( _GFILLINTERIOR, x, y, x+width, y+height );
  1365.       x += width + 1;                /* Advance to next col    */
  1366.       color = 1 + (color % (MaxColors - 2));    /* Set new color    */
  1367.     }                /* End of COLUMN loop        */
  1368.     x = 0;                /* Goto 1st column        */
  1369.     y += height + 1;            /* Goto next row        */
  1370.   }                    /* End of ROW loop        */
  1371.  
  1372.   while( !kbhit() )
  1373.   {            /* Until user enters a key...    */
  1374.     relt = random (64);
  1375.     gelt = random (64);
  1376.     belt = random (64);
  1377.     _remappalette( 1+random(MaxColors-2), RGB(relt,gelt,belt) );
  1378.   }
  1379.  
  1380. //  setallpalette( &palette );
  1381.   /* Reset video mode to get palette back to its defaults */
  1382.   _setvideomode (_MAXRESMODE);
  1383.  
  1384.   Pause();                /* Wait for user's response     */
  1385.  
  1386. }
  1387.  
  1388. /*                                    */
  1389. /*    POLYDEMO: Display a random pattern of polygons on the screen    */
  1390. /*    until the user says enough.                    */
  1391. /*                                    */
  1392.  
  1393. #define MaxPts        6        /* Maximum # of pts in polygon    */
  1394.  
  1395. void PolyDemo(void)
  1396. {
  1397.   struct xycoord poly[ MaxPts ];        /* Space to hold datapoints    */
  1398.   int color;                /* Current drawing color    */
  1399.   int i;
  1400.  
  1401.   MainWindow( "Polygon Draw/Fill Demonstration" );
  1402.   StatusLine( "ESC Aborts - Press a Key to stop" );
  1403.  
  1404.   while( !kbhit() )
  1405.   {            /* Repeat until a key is hit    */
  1406.  
  1407.     for( i=0 ; i<(MaxPts-1) ; i++ )
  1408.     {    /* Determine a random polygon    */
  1409.       poly[i].xcoord = random( MaxX );    /* Set the x coord of point    */
  1410.       poly[i].ycoord = random( MaxY );    /* Set the y coord of point    */
  1411.     }
  1412.  
  1413.     poly[i].xcoord = poly[0].xcoord;        /* last point = first point    */
  1414.     poly[i].ycoord = poly[1].ycoord;
  1415.  
  1416.     _setcolor( BLACK );            /* Clear out area behind polygon */
  1417.     _polygon( _GBORDER, poly, MaxPts );      /* Draw a black border */
  1418.     _polygon( _GFILLINTERIOR, poly, MaxPts );  /* Draw a black polygon        */
  1419.     color = 1 + random( MaxColors-1 );    /* Get a random color # (no blk)*/
  1420.     _setfillmask( patterns[random(10)] );    /* Set a random fill style    */
  1421.     _setcolor( color );            /* Set the desired color    */
  1422.  
  1423.     _polygon( _GBORDER, poly, MaxPts );      /* Draw the polygon border */
  1424.     _polygon( _GFILLINTERIOR, poly, MaxPts );      /* Draw the actual polygon        */
  1425.   }                    /* End of WHILE not KBHIT    */
  1426.  
  1427.   Pause();                /* Wait for user's response     */
  1428.  
  1429. }
  1430.  
  1431.  
  1432. /*                                    */
  1433. /*    SAYGOODBYE: Give a closing screen to the user before leaving.    */
  1434. /*                                    */
  1435.  
  1436. void SayGoodbye(void)
  1437. {
  1438.   struct viewporttype viewinfo;     /* Structure to read viewport    */
  1439.   int h, w, font, lwidth;
  1440.  
  1441.   MainWindow( "== Finale ==" );
  1442.  
  1443.   viewinfo.left    = curr_vp.left;
  1444.   viewinfo.top    = curr_vp.top;
  1445.   viewinfo.right = curr_vp.right;
  1446.   viewinfo.bottom = curr_vp.bottom;
  1447.   font = roman_ndx;
  1448.   changetextstyle( Fonts[font].facename, HORIZ_DIR,
  1449.              Fonts[font].pixheight,
  1450.              Fonts[font].avgwidth );
  1451.  
  1452.   h = viewinfo.bottom - viewinfo.top;
  1453.   w = viewinfo.right    - viewinfo.left;
  1454.   lwidth = _getgtextextent ( "That's all, folks!" );
  1455.   cp = _moveto( (w-lwidth)/2, h/2 );
  1456.   _outgtext ( "That's all, folks!" );
  1457.   cp = _getcurrentposition ();
  1458.  
  1459.   StatusLine( "Press any key to EXIT" );
  1460.   getch();
  1461.  
  1462.   _clearscreen(_GCLEARSCREEN);            /* Clear the graphics screen    */
  1463.  
  1464. }
  1465.  
  1466. /*                                    */
  1467. /*    PAUSE: Pause until the user enters a keystroke. If the        */
  1468. /*    key is an ESC, then exit program, else simply return.        */
  1469. /*                                    */
  1470.  
  1471. void Pause(void)
  1472. {
  1473.   static char msg[] = "Esc aborts or press a key...";
  1474.   int c;
  1475.  
  1476.   StatusLine( msg );            /* Put msg at bottom of screen    */
  1477.  
  1478.   c = getch();                /* Read a character from kbd    */
  1479.  
  1480.   if( ESC == c )
  1481.   {            /* Does user wish to leave?    */
  1482.     _setvideomode( _DEFAULTMODE );    /* Change to text mode        */
  1483.     exit( 1 );                /* Return to OS         */
  1484.   }
  1485.  
  1486.   if( c == 0 )
  1487.   {            /* Did use hit a non-ASCII key? */
  1488.     c = getch();            /* Read scan code for keyboard    */
  1489.   }
  1490.  
  1491.   _clearscreen(_GCLEARSCREEN);            /* Clear the screen        */
  1492.  
  1493. }
  1494.  
  1495. /*                                    */
  1496. /*    MAINWINDOW: Establish the main window for the demo and set    */
  1497. /*    a viewport for the demo code.                    */
  1498. /*                                    */
  1499.  
  1500. void MainWindow( char *header )
  1501. {
  1502.   int height, twidth, font;
  1503.  
  1504.   _clearscreen(_GCLEARSCREEN);            /* Clear graphics screen    */
  1505.   _setcolor( MaxColors - 1 );        /* Set current color to white    */
  1506.   curr_vp.left     = 0;            /* Initial & current viewport */
  1507.   curr_vp.top     = 0;
  1508.   curr_vp.right  = MaxX;
  1509.   curr_vp.bottom = MaxY;
  1510.   _setviewport( 0, 0, MaxX, MaxY );    /* Open port to full screen    */
  1511.  
  1512.   height = Fonts[dfont_ndx].pixheight;    /* Get basic text height    */
  1513.   font = dfont_ndx;
  1514.   changetextstyle( Fonts[font].facename, HORIZ_DIR, height,
  1515.              Fonts[font].avgwidth );
  1516.   /* Need to center text ourselves */
  1517.   twidth = _getgtextextent ( header );
  1518.   cp = _moveto( (MaxX-twidth)/2, 2 );
  1519.   _outgtext ( header );
  1520.   cp = _getcurrentposition ();
  1521.   curr_vp.left     = 0;
  1522.   curr_vp.top     = height+4;
  1523.   curr_vp.right  = MaxX;
  1524.   curr_vp.bottom = MaxY-(height+4);
  1525.   _setviewport( 0, height+4, MaxX, MaxY-(height+4) );
  1526.   DrawBorder();
  1527.   curr_vp.left     = 1;
  1528.   curr_vp.top     = height+5;
  1529.   curr_vp.right  = MaxX-1;
  1530.   curr_vp.bottom = MaxY-height+5;
  1531.   _setviewport( 1, height+5, MaxX-1, MaxY-(height+5) );
  1532.  
  1533. }
  1534.  
  1535. /*                                    */
  1536. /*    STATUSLINE: Display a status line at the bottom of the screen.    */
  1537. /*                                    */
  1538.  
  1539. void StatusLine( char *msg )
  1540. {
  1541.   int height, twidth, font;
  1542.  
  1543.   curr_vp.left     = 0;
  1544.   curr_vp.top     = 0;
  1545.   curr_vp.right  = MaxX;
  1546.   curr_vp.bottom = MaxY;
  1547.   _setviewport( 0, 0, MaxX, MaxY );    /* Open port to full screen    */
  1548.   _setcolor( MaxColors - 1 );        /* Set current color to white    */
  1549.  
  1550.   font = dfont_ndx;
  1551.   height = Fonts[dfont_ndx].pixheight;         /* Detemine current height     */
  1552.   changetextstyle( Fonts[font].facename, HORIZ_DIR, height,
  1553.              Fonts[font].avgwidth );
  1554.  
  1555.   _setlinestyle( SOLID_STYLE );
  1556.   _setfillmask( patterns[EMPTY_FILL] );
  1557.  
  1558.   _rectangle( _GBORDER, 0, MaxY-(height+4), MaxX, MaxY );
  1559.   /* Need to center text ourselves */
  1560.   twidth = _getgtextextent ( msg );
  1561.   cp = _moveto( (MaxX-twidth)/2, MaxY-(height+2) );
  1562.   _outgtext ( msg );
  1563.   cp = _getcurrentposition ();
  1564.   curr_vp.left     = 1;
  1565.   curr_vp.top     = height+5;
  1566.   curr_vp.right  = MaxX-1;
  1567.   curr_vp.bottom = MaxY-(height+5);
  1568.   _setviewport( 1, height+5, MaxX-1, MaxY-(height+5) );
  1569.  
  1570. }
  1571.  
  1572. /*                                    */
  1573. /*    DRAWBORDER: Draw a solid single line around the current     */
  1574. /*    viewport.                            */
  1575. /*                                    */
  1576.  
  1577. void DrawBorder(void)
  1578. {
  1579.   struct viewporttype vp;
  1580.  
  1581.   _setcolor( MaxColors - 1 );        /* Set current color to white    */
  1582.  
  1583.   _setlinestyle( SOLID_STYLE );
  1584.  
  1585.   vp.left   = curr_vp.left;
  1586.   vp.top    = curr_vp.top;
  1587.   vp.right  = curr_vp.right;
  1588.   vp.bottom = curr_vp.bottom;
  1589.   _rectangle( _GBORDER, 0, 0, vp.right-vp.left, vp.bottom-vp.top );
  1590.  
  1591. }
  1592.  
  1593. /*                                    */
  1594. /* Note 21 - CHANGETEXTSTYLE: similar to Borland C++ settextstyle, but     */
  1595. /*         checks forerrors that might occur while loading the font     */
  1596. /*         file.                            */
  1597. /*                                    */
  1598.  
  1599. void changetextstyle(char *font, int direction, int charht, int charwid)
  1600. /* font is name of typeface */
  1601. /* direction is orientation - horizontal or vertical */
  1602. /* charht and charwid are used only for vector fonts */
  1603. {
  1604.   int ErrorCode;
  1605.   unsigned char list[50];
  1606.     /* Construct string of font characteristics */
  1607.     sprintf( list, "t'%s'h%dw%d", font, charht, charwid );
  1608.     /* Select the font */
  1609.     ErrorCode =_setfont( list );
  1610.     if( ErrorCode >= 0 )
  1611.     {
  1612.     }
  1613.     /* Set up direction for _outgtext */
  1614.     if (direction == HORIZ_DIR)
  1615.       _setgtextvector ( 1, 0 );
  1616.     else
  1617.       _setgtextvector ( 0, 1 );
  1618. }
  1619.  
  1620. /*                                    */
  1621. /*    GPRINTF: Used like PRINTF except the output is sent to the    */
  1622. /*    screen in graphics mode at the specified co-ordinate.        */
  1623. /*                                    */
  1624.  
  1625. int gprintf( int *xloc, int *yloc, char *fmt, ... )
  1626. /* Must be used with _setfont for default font with index dfont_ndx */
  1627. {
  1628.   va_list  argptr;            /* Argument list pointer    */
  1629.   char str[140];            /* Buffer to build sting into    */
  1630.   int cnt;                /* Result of SPRINTF for return */
  1631.  
  1632.   va_start( argptr, fmt );        /* Initialize va_ functions    */
  1633.  
  1634.   cnt = vsprintf( str, fmt, argptr );    /* prints string to buffer    */
  1635.   cp = _moveto( *xloc, *yloc );
  1636.   _outgtext ( str );    /* Send string in graphics mode */
  1637.   cp = _getcurrentposition ();
  1638.   *yloc += Fonts[dfont_ndx].pixheight + 2;    /* Advance to next line     */
  1639.  
  1640.   va_end( argptr );            /* Close va_ functions        */
  1641.  
  1642.   return( cnt );            /* Return the conversion count    */
  1643.  
  1644. }
  1645. /* Note 22 - the delay function pauses for wait microseconds. */
  1646. void delay( clock_t wait )
  1647. {
  1648.     clock_t goal;
  1649.  
  1650.     goal = wait + clock();
  1651.     while( goal > clock() )
  1652.     ;
  1653. }
  1654.